package com.visionblue.business.ship.print

import android.content.Context
import android.hardware.usb.UsbManager
import com.hoho.android.usbserial.driver.UsbSerialPort
import com.hoho.android.usbserial.driver.UsbSerialProber
import com.hoho.android.usbserial.util.SerialInputOutputManager
import com.visionblue.business.ship.util.GBKHexUtil
import com.visionblue.business.ship.util.MLog
import com.visionblue.business.ship.util.ext.closeSilently
import java.io.IOException
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors


/**
 * @author: xlh
 * @date: 2020-06-17 6:45 PM
 * @desc:
 */
class UsbSerialPrinter(val context: Context) : IPrinter {

    private var mSerialPort: UsbSerialPort? = null

    private var mSerialIoManager: SerialInputOutputManager? = null

    private val mExecutor: ExecutorService = Executors.newSingleThreadExecutor()

    @Synchronized
    override fun print(byteArray: ByteArray) {

        MLog.e(GBKHexUtil.bytes2HexString(byteArray))
        if (mSerialPort == null) {
            init()
            write(byteArray)
        } else {
            write(byteArray)
        }
    }

    private fun init() {
        val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager?

        if (usbManager != null) {
            val drivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager)
            val result = mutableListOf<UsbSerialPort>()
            drivers.forEach { driver ->
                val ports = driver.ports
                MLog.d("+ $driver : ${ports.size} ports")
                result.addAll(ports)
            }

            if (result.isNotEmpty()) {
                mSerialPort = result[0]
                val conn = usbManager.openDevice(mSerialPort?.driver?.device)
                    ?: throw OpenPrinterException()

                try {
                    mSerialPort?.open(conn)
                    mSerialPort?.setParameters(
                        115200,
                        UsbSerialPort.DATABITS_8,
                        UsbSerialPort.STOPBITS_1,
                        UsbSerialPort.PARITY_NONE
                    )
                    stopIoManager()
                    startIoManager()
                } catch (e: IOException) {
                    mSerialPort.closeSilently()
                    mSerialPort = null
                    throw OpenPrinterException()
                }
            } else {
                throw OpenPrinterException()
            }
        }
    }

    private fun write(byteArray: ByteArray) {
        if (mSerialPort != null) {
            try {
                mSerialPort?.write(byteArray, 1000)
            } catch (e: IOException) {
//                MLog.e(e.message.toString())
                throw PrinterWriteException()
            }
        }
    }

    private fun stopIoManager() {
        //停止
        mSerialIoManager?.stop()
        mSerialIoManager = null
    }

    private fun startIoManager() {
        if (mSerialPort != null) { //启动io管理器
            mSerialIoManager = SerialInputOutputManager(mSerialPort, mListener)
            mExecutor.submit(mSerialIoManager)
        }
    }

    private val mListener: SerialInputOutputManager.Listener =
        object : SerialInputOutputManager.Listener {
            override fun onRunError(e: Exception) {
                MLog.d("Runner stopped.")
            }

            override fun onNewData(data: ByteArray) { //发送
                MLog.d("onNewData: $data")
            }
        }


}